package com.lfy.websocket;

import com.lfy.websocket.handler.ChatHandler;
import com.lfy.websocket.handler.HttpHeadersHandler;
import com.lfy.websocket.handler.NettyCollectorHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.NettyRuntime;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * webSocket服务端
 *
 * @author <a href="https://www.lvfeiy.top">lvfeiyang</a>
 * @date 2024/6/22 14:51
 */
@Component
@Slf4j
public class NettyServer {

    private static final EventLoopGroup BOSS_GROUP = new NioEventLoopGroup(1);

//   private static final EventLoopGroup WORKER_GROUP = new NioEventLoopGroup(NettyRuntime.availableProcessors());
    private static final EventLoopGroup WORKER_GROUP = new NioEventLoopGroup(2);

    public static final int WEB_SOCKET_PORT = 8090;

    private static Channel channel;

    {
        log.info("webSocket create bean ....................");
    }

    @PostConstruct
    public void init() {
        start();
    }

    public void start() {
        ChannelFuture future = new ServerBootstrap()
                .group(BOSS_GROUP, WORKER_GROUP)
                .channel(NioServerSocketChannel.class)
                //最大128个tcp连接队列
                .option(ChannelOption.SO_BACKLOG, 128)
                //保活连接
                .option(ChannelOption.SO_KEEPALIVE, true)
                //日志
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                ChannelPipeline pipeline = channel.pipeline();
                //http解码器
                pipeline.addLast(new HttpServerCodec());
                //对大数据流写提供支持
                pipeline.addLast(new ChunkedWriteHandler());
                //对httpMessage进行聚合处理，聚合成Response和Request
                pipeline.addLast(new HttpObjectAggregator(1024 * 64));
                pipeline.addLast(new HttpHeadersHandler());
                //连接地址
                pipeline.addLast(new WebSocketServerProtocolHandler("/"));
                //自定义处理器
                pipeline.addLast(new NettyCollectorHandler());
                pipeline.addLast(new ChatHandler());

            }
        }).bind(WEB_SOCKET_PORT);
        try {
            Channel channel = future.sync().channel();

            ChannelFuture closeFuture = channel.closeFuture();
            closeFuture.addListener(f -> {

                log.info("netty webSocket server close");
            });
        } catch (InterruptedException e) {
            log.error("关闭资源异常",e);
        }

    }
    @PreDestroy
    public void destroy() {
        Future<?> bossFuture = BOSS_GROUP.shutdownGracefully();
        Future<?> workerFuture = WORKER_GROUP.shutdownGracefully();
        bossFuture.syncUninterruptibly();
        workerFuture.syncUninterruptibly();
        log.info("webSocket pool close");
    }
}
